package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ApArticleConfigService;
import com.heima.article.service.ApArticleContentService;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ArticleFreemarkerService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.constants.BehaviorConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.dtos.ArticleCommentDto;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.dtos.ArticleInfoDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.vos.ArticleCommnetVo;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.ArticleVisitStreamMess;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 文章信息表，存储已发布的文章 服务实现类
 * </p>
 *
 * @author itheima
 */
@Slf4j
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {

    @Autowired
    ApArticleMapper apArticleMapper;

    @Autowired
    ApArticleContentService articleContentService;

    @Autowired
    ApArticleConfigService articleConfigService;

    @Autowired
    ArticleFreemarkerService articleFreemarkerService;

    @Autowired
    CacheService cacheService;

    @Override
    public ResponseResult loadArticle(ArticleHomeDto dto, int type) {
        return ResponseResult.okResult(apArticleMapper.loadArticle(dto,type));
    }

    @Override
    public ResponseResult loadArticle2(ArticleHomeDto dto, int type, boolean isFirst) {
        if(isFirst){
            String jsonArray = cacheService.get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + dto.getTag());
            if(StringUtils.isNotBlank(jsonArray)){
                List<HotArticleVo> voList = JSON.parseArray(jsonArray, HotArticleVo.class);
                //如果缓存数据较少
                if(voList.size()<10){
                    List<ApArticle> all =new ArrayList<>();
                    List<Long> idList = voList.stream().map(HotArticleVo::getId).collect(Collectors.toList());
                    all.addAll(voList);
                    List<ApArticle> articleList = apArticleMapper.loadArticle(dto, type);
                    for (ApArticle apArticle : articleList) {
                        if(!idList.contains(apArticle.getId())){
                            all.add(apArticle);
                        }
                    }
                    return ResponseResult.okResult(all);
                }else{
                    return ResponseResult.okResult(voList);
                }
            }
        }
        return loadArticle(dto,type);
    }

    //service内部
    @Override
    public ResponseResult saveArticle(ArticleDto dto) {

        //保存app_article
        ApArticle apArticle = new ApArticle();
        BeanUtils.copyProperties(dto,apArticle);
        this.save(apArticle);

        //保存app_article_content
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(dto.getContent());
        articleContentService.save(apArticleContent);

        //保存app_article_config
        ApArticleConfig apArticleConfig = new ApArticleConfig(apArticle.getId());
        articleConfigService.save(apArticleConfig);

        //文章静态化
        try {
            articleFreemarkerService.buildArticleToMinIO(apArticle, dto.getContent());
        } catch (Exception e) {
            return ResponseResult.errorResult(AppHttpCodeEnum.FILE_STATICURL_ERROR);
           // e.printStackTrace();
        }
        return ResponseResult.okResult(apArticle.getId());
    }

    @Override
    public PageResponseResult findNewsComments(ArticleCommentDto dto) {
        Integer currentPage = dto.getPage();
        dto.setPage((dto.getPage()-1)*dto.getSize());
        List<ArticleCommnetVo> list = apArticleMapper.findNewsComments(dto);
        int count = apArticleMapper.findNewsCommentsCount(dto);

        PageResponseResult responseResult = new PageResponseResult(currentPage,dto.getSize(),count);
        responseResult.setData(list);
        return responseResult;
    }


    @Override
    public void updateScore(ArticleVisitStreamMess articleVisitStreamMess) {
       //1 修改数据库
        ApArticle apArticle = this.getById(articleVisitStreamMess.getArticleId());
        apArticle.setViews(apArticle.getViews()+articleVisitStreamMess.getView());
        apArticle.setCollection(apArticle.getCollection()+articleVisitStreamMess.getCollect());
        apArticle.setComment(apArticle.getComment()+articleVisitStreamMess.getComment());
        apArticle.setLikes(apArticle.getLikes()+articleVisitStreamMess.getLike());
        this.updateById(apArticle);
        //2 更新缓存
        //2.1 从新计算权重
        int articleScore = computeArticleScore(apArticle);
        HotArticleVo vo = new HotArticleVo();
        BeanUtils.copyProperties(apArticle,vo);
        vo.setScore(articleScore*3); //实时计算的权重3倍

        String json = cacheService.get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + apArticle.getChannelId());
        if(StringUtils.isNotBlank(json)){
            List<HotArticleVo> voList = JSON.parseArray(json, HotArticleVo.class);
            //替换规则
            if(voList.size()>=30){
                HotArticleVo last = voList.get(voList.size() - 1);
                //如果满的时候，最后一个数据比当前的小，替换
                if(last.getScore()<vo.getScore()){
                    voList.remove(last);
                    voList.add(vo);
                }
            }else{
                //缓存缓存队列不满
                voList.add(vo);
            }
            //从新排序
            Collections.sort(voList, (HotArticleVo o1, HotArticleVo o2)-> o2.getScore()-o1.getScore());
            //更新缓存
            cacheService.set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + apArticle.getChannelId(),JSON.toJSONString(voList));
        }else{
            //如果缓存没有数据
            ArrayList<HotArticleVo> hotArticleVos = new ArrayList<>();
            hotArticleVos.add(vo);
            cacheService.set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + apArticle.getChannelId(),JSON.toJSONString(hotArticleVos));
        }
    }


    private int computeArticleScore(ApArticle apArticle) {
//        阅读权重：1
//        点赞权重：3
//        评论权重：5
//        收藏权重：8

        int score =0;
        if(apArticle.getViews()!=null){
            score+=apArticle.getViews();
        }
        if(apArticle.getLikes()!=null){
            score+=apArticle.getLikes()*3;
        }
        if(apArticle.getComment()!=null){
            score+=apArticle.getComment()*5;
        }
        if(apArticle.getCollection()!=null){
            score+=apArticle.getCollection()*8;
        }
        return score;
    }


}
